﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using network;
using System.Net;
using System.Configuration;
using System.Threading;

namespace FailoverClusterController
{
    public partial class FailoverServiceViCOS : ServiceBase
    {
        Election election;
        NonLeader client;

        Boolean isRunning;
        private string NIC;


        public FailoverServiceViCOS()
        {
            InitializeComponent();

            // Get the path for the background Image from app.Config
            this.NIC = ConfigurationManager.AppSettings["NIC"];


            // Initialize FailoverEventLog   
            if (!System.Diagnostics.EventLog.SourceExists("FailoverSource"))
                System.Diagnostics.EventLog.CreateEventSource("FailoverSource", "FailoverEventLog");
            FailoverEventLog.Log = "FailoverEventLog";
            FailoverEventLog.Source = "FailoverSource";
            
        }

        private void log(string str)
        {
            FailoverEventLog.Source = "FailoverSource";
            FailoverEventLog.WriteEntry(str);
        }


        protected override void OnStart(string[] args) // Recieves the NIC to operate on
        {
            log("ViCOS Failover Cluster Controller Service started.");

            if (this.NIC == "0.0.0.0" || this.NIC == "")
            {
                log("Unspecified network interface. Reinstall ViCOS Failover Cluster Controller with a valid Interface.");
                this.isRunning = false;
            }
            else
            {
                log(String.Format("Using {0} interface", this.NIC));
                this.isRunning = true;
                
                Thread workingThread = new Thread(new ThreadStart(workingThreadHandler));
                workingThread.Start();
            }

            base.OnStart(args);

        }

        private void workingThreadHandler()
        {
            election = new Election(FailoverEventLog, IPAddress.Parse(this.NIC));
            election.invokeElection();

            // start the client work
            // the contructor uses the election info to send data to leader when the VMs change.
            client = new NonLeader(FailoverEventLog, election, IPAddress.Parse(this.NIC));
            // set the event handler for VM changes.
            client.start();

            while (this.isRunning)
            {
                if (!election.electionInfo.electionRunning)
                {
                    if (election.electionInfo.myID == election.electionInfo.leader.ID)
                    {
                        // start the leader work
                        // the constructor already start the UDPServer class
                        log(String.Format("Working as Leader. ID: {0}", election.electionInfo.myID));
                        Leader leader = new Leader(FailoverEventLog, election.electionInfo);
                        leader.noMoreLeader.WaitOne(); //wait fot the set()
                    }
                    else
                    {
                        // wait until a leader timeout
                        // then go back to begin and start a new election.
                        log("Working as Non-Leader.");
                        client.mre.WaitOne();
                        election.invokeElection();
                        client.mre.Reset();
                    }
                }
            }
        }


        protected override void OnStop()
        {
            isRunning = false;
            // precisa mandar um evendo falando pro lider ou pro client largar o osso
            log("ViCOS Failover Cluster Controller Service stopped.");
        }
    }
}
